home *** CD-ROM | disk | FTP | other *** search
- /*
- * LockMon: determine the number of locks associated with a filesystem
- * task. I haven't figured out how to do this directly, so I
- * cheat -- if a volume is offlined, then a linked list of locks
- * is transferred to the volume's DeviceList entry. Note that
- * this isn't a permanent solution -- it won't work with hard
- * disks or RAM:, for instance.
- *
- * Warnings: Uses Aztec C library internal DOSBase, which holds the
- * DOS library base pointer. Lattice does the same.
- * And ... this implementation is guesswork. Caveat emptor!
- *
- * Request: Anybody know a better way?
- *
- * Perpetrator: Dewi Williams ..!ihnp4!druca!dewi.
- * Extremely public domain.
- *
- * Version: 1.0
- */
-
- #include <stdio.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <exec/memory.h>
-
- /* Defines */
-
- /* Change typeless BCPL BPTR to typed C (for struct pointers). Don't
- * use this define on an APTR, that's only a badly disguised void *.
- */
- #define BPTR_TO_C(strtag, var) ((struct strtag *)(BADDR( (ULONG) var)))
-
- /* And do the reverse */
- #define C_TO_BPTR(var) (((ULONG)var)>>2)
-
- /* Externs */
- extern struct DosLibrary *DOSBase; /* dos library base pointer */
- extern short Enable_Abort; /* controls ^C processing */
-
- /* ARGSUSED */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- struct RootNode *rn;
- struct DosInfo *di;
- struct DeviceList *dl;
- struct FileLock *myFileLock;
- struct Process *myprocess;
- char buf[80];
- struct FileInfoBlock *fi;
- char *name;
- char *btocstr();
- void *malloc();
- void CountLocks();
- struct Task *FindTask();
-
- Enable_Abort = 0; /* Disable ^C processing */
-
- printf("Eject any volumes you wish to profile.\n");
- printf("You will be requested to re-insert them as needed.\n");
- printf("When ready, press RETURN to continue or 'q' to abort.\n");
- (void)gets(buf); /* Well, q and RETURN really... */
-
- if (buf[0] == 'q') { /* Last chance to change your mind! */
- printf("Aborted...\n");
- exit(0);
- }
-
- /* Wait for things to settle down (just in case) */
- (void)Delay(5 * TICKS_PER_SECOND);
-
- /* The FileInfoBlock with guaranteed alignment. */
- if ((fi = (struct FileInfoBlock *)malloc(sizeof(*fi) )) == NULL) {
- printf("Memory allocation failure");
- exit(1);
- }
-
- /* Note that since lockmon itself has a lock on the current
- * directory, this has to be filtered out as an artefact.
- * We can get its value out of the CLI stuff. Our task control
- * block is the first element of the process control block,
- * hence the following casting. This code fragment courtesy of
- * the kind person at C-A who answered my query about finding
- * the current directory on RAM:
- */
- myprocess = (struct Process *)FindTask(NULL);
-
- myFileLock = BPTR_TO_C(FileLock, myprocess->pr_CurrentDir);
-
- /* Any system manipulation of AmigaDOS linked lists while we're
- * traversing could quite easily crash us, and the system. So
- * we righteously forbid it.
- */
- Forbid(); /* but is this really necessary? */
-
- /* Take the DOS library base pointer, deduce the DOS Root Node
- * address from that. Follow this to the Info substructure, which
- * gives us the start address of the DeviceList chain. Volumes are
- * DeviceList entries with a type of DLT_VOLUME. Note that these are
- * AmigaDOS linked lists *NOT* Exec ones, so all the stuff about List,
- * Node etc. doesn't apply. One box, 2 operating systems!
- */
- rn = (struct RootNode *)DOSBase->dl_Root;
- di = BPTR_TO_C(DosInfo, rn->rn_Info);
- dl = BPTR_TO_C(DeviceList, di->di_DevInfo);
-
- while (dl != NULL) {
- if (dl->dl_Type == DLT_VOLUME) {
- if ((name = btocstr(dl->dl_Name)) == NULL) {
- printf("Memory allocation failure\n");
- break;
- }
- printf("Volume '%s': ", name);
- if (dl->dl_LockList != NULL) {
- CountLocks(BPTR_TO_C(FileLock,dl->dl_LockList),
- fi, myFileLock);
- } else {
- /* Either mounted or no locks... */
- if (dl->dl_Task == NULL)
- printf(": no locks\n");
- else
- printf(": mounted\n");
- }
- free(name);
- }
- dl = BPTR_TO_C(DeviceList, dl->dl_Next);
- }
-
- Permit(); /* Multi-tasking now back on */
- free(fi);
- exit(0);
- }
-
- /*
- * Traverse the linked lists of locks, counting them and printing out their
- * corresponding filesystem names.
- */
-
- void
- CountLocks(list, fi, mylock)
- struct FileLock *list; /* the linked list to run through */
- struct FileInfoBlock *fi; /* area for Examine */
- struct FileLock *mylock; /* this one's ours */
- {
- register struct FileLock *lptr;
- register int count = 0;
- short Examine();
-
- for(lptr=list;lptr != NULL; lptr= BPTR_TO_C(FileLock,lptr->fl_Link)){
- if (lptr == mylock) continue;
-
- if (Examine(C_TO_BPTR(lptr), fi) == FALSE) {
- /* Clicked Cancel on system requester ? */
- printf("\n\tCannot deduce filename for lock");
- } else {
- printf("\n\t%s", fi->fib_FileName);
- }
- count++;
-
- }
- if (count > 0)
- printf("\nTotal: %d lock(s)\n", count);
- else
- printf(": no locks\n");
- }
-
- /*
- * Convert a BCPL string to a C string. To avoid scrogging in-memory
- * stuff, it malloc's off a copy first.
- */
-
- char *
- btocstr(b)
- ULONG b;
- {
- register char *p, *s;
- void *malloc();
-
- s = (char *)BADDR(b); /* Shift & get length-prefixed str */
-
- if ((p = malloc(s[0])) != NULL) {
- (void)movmem(s +1, p, s[0]); /* Aztec memcpy */
- p[s[0]] = '\0';
- }
- return p;
- }
-